 
import { ATeamCombat } from "GameLoop/WorldState/EntityManager/Entitys";
import { TeamUtils } from "./TeamUtils";
import { UtilsHelper } from "utils/position/UtilsHelper";
import { default_visual_text_style } from "utils/constants/globalconstant";
import { CreepAbilityHelper } from "utils/creep/CreepAbilityHelper";
import { Math2D } from "algorithm/Math2d";

export class TeamMoveUtils
{
    /**
     * 移动到沼泽
     * @param team 
     * @param dir 
     * @param roomName 
     * @returns 
     */
    public static isMoveToSWAMP(team:ATeamCombat, dir:DirectionConstant|0, roomName:string)
    {
        const poss = _.map(team.creeps,e=>e.pos);
        let nextCheckPos:RoomPosition[]=poss;
        if(dir)
        {
           let nextTeamPos =   _.map(poss,e=> UtilsHelper.GetDirectionPos(e,dir))  ;
           nextCheckPos = nextTeamPos
        }
        for(const e of nextCheckPos)
        {
           const terrain = Game.rooms[e.roomName].getTerrain();
           if(terrain.get(e.x,e.y) == TERRAIN_MASK_SWAMP)
           {
               return true;
           }
        }
        return false;
    }
    /**
     * 能够安全的移动
     * @param team 
     * @param dir 
     * @param roomName 
     * @returns 
     */
    public static  isSqareSafeMoveable(team:ATeamCombat, dir:DirectionConstant, roomName:string)
    {
        const creeps = team.creeps;
        const poss = _.map(creeps,e=>e.pos);
        const code = TeamUtils.IsPositionsMoveable(poss,dir);
        if(code === OK || code ===2)
        {
            if(this.getDangerousFactor(team,dir,roomName, code==2?true:false)>1)
            {
                return false;
            }
            return true;
        }


        return false;
    }
    /**
     * * 获取危险系数 敌方最大伤害/我方总治疗值
     * @param team 小队
     * @param direction 目标方向 用于计算下一个位置
     * @param roomName
     * @param radio    系数值 在平地上可能只会被打一次  在沼泽上可能会被打5次才能走掉
     *  @param damagescale  伤害放大系数
     * @returns
     */
    public static getDangerousFactor(team:ATeamCombat,direction:DirectionConstant|0,roomName:string,isswap:boolean ):number
    {
      
        let extand_range=isswap?3:0;
        let radio = isswap?5:1;
        const team_max_heal = team.getTeamHealMax();
        const mycreeps:Creep[]=team.creeps;
 
        let lost_hits=0;
        for(const e of mycreeps)
        {
            // team.log('info','assert1aaa')
            const nextpos =  UtilsHelper.GetDirectionPos(e.pos,direction);
            e.nextpos=nextpos;
            lost_hits+=(e.hitsMax-e.hits);
            
        }
      
        const cachecreeps =  global.world.PollHostiles(roomName);
        const hostiles = _.filter(team.aroundHostileCreeps,e=>
            {
                if(cachecreeps)
                {
                    if(cachecreeps.hostileCreepAbility[e.id] && cachecreeps.hostileCreepAbility[e.id][1])
                    {
                        return true;
                    }
                }
                return false;
            })
        const team_max_bedamge = this.maxDamage(mycreeps,hostiles,roomName,extand_range);
        if(team_max_heal<team_max_bedamge)
        {
            for(const e of mycreeps)
            {
                Game.rooms[roomName].visual.text(`危:${team_max_bedamge}/${team_max_heal}`,e .nextpos.x,e .nextpos.y,default_visual_text_style);
            }

        }
        
        // global.LogDebug(`${JSON.stringify(_.map(mycreeps,e=>e.nextpos))} 危:${team_max_bedamge}/${team_max_heal}`);
        const damage =team_max_bedamge+lost_hits;
        if(damage<team_max_heal)
        {
            return damage/team_max_heal;
        }
        return ((damage-team_max_heal)*radio+ team_max_heal)/team_max_heal;
    }


       /**
         * 计算小队可能承受到的最大伤害
         * @param mycreeps
         * @param hostiles
         * @param roomName
         * @param extend_range 地方额外的攻击范围。当我在沼泽内时，地方8格内的单位都能打到我。因为移动一次需要5T
         * @returns
         */
    protected static maxDamage(mycreeps:Creep[],hostiles:Creep[],roomName:string,extend_range:number=0):number
    {
        // 计算范围伤害
        const massdamage:Record<number,number>={};
        // 计算可能的伤害
        const possible_atk:Record<number,number>={};
        //  爬的最终可能承伤
        const possible_real_damge:Record<number,number>={};

        for(const e of mycreeps)
        {
            massdamage[e.nextpos.to1D()]=0;
            possible_atk[e.nextpos.to1D()]=0;
            possible_real_damge[e.nextpos.to1D()]=0;
        }
        let possdamage_max = 0;
        const cachestructures =  global.world.PollStructure(roomName);
        const cachecreeps =  global.world.PollHostiles(roomName);

        if(cachecreeps && cachecreeps.hostileCreepAbility)
        {
            if(extend_range)
            {
                possdamage_max = this.possibleMaxDamage(hostiles,cachecreeps.hostileCreepAbility,)
            }
            for(const e of mycreeps)
            {
                massdamage[e.nextpos.to1D()]=cachecreeps.inquireMassDamage(e.pos);
                possible_atk[e.nextpos.to1D()]=cachecreeps.inquirePossibleDamage(e.pos);
            }
        }

        // 计算爬可能的真是承受伤害
        if(!Game.rooms[roomName].controller?.my &&cachestructures && cachestructures.TowerDamage.length>0)
        {
         for(const e of mycreeps)
         {
             let tower_damage =cachestructures.inquireDamage(e.pos);
             let mass_damage = massdamage[e.nextpos.to1D()];
             let poss_damage = possible_atk[e.nextpos.to1D()];
             possible_real_damge[e.nextpos.to1D()]=CreepAbilityHelper.GetRealBearDamage(e,tower_damage+mass_damage+poss_damage);
         }

        }
        else
        {
            for(const e of mycreeps)
            {
                let mass_damage = massdamage[e.nextpos.to1D()];
                let poss_damage = possible_atk[e.nextpos.to1D()];
                possible_real_damge[e.nextpos.to1D()]=CreepAbilityHelper.GetRealBearDamage(e,mass_damage+poss_damage);
            }
        }

        // 最大伤害则为爬的可能承受真实伤害 + 其他爬承受的真实mass伤害之和
        const getMaxDamgePossible=(creep:Creep,creeps:Creep[])=>
        {
            let sum=0;
            for(const e of creeps)
            {
                if(e.name == creep.name)
                {
                    sum+=Math.max(possdamage_max, possible_real_damge[e.nextpos.to1D()]);
                }
                else
                {
                    sum+=CreepAbilityHelper.GetRealBearDamage(e,massdamage[e.nextpos.to1D()]);
                }
            }
            return sum
        }

        let sum_maxDamage=0;
        for(const e of mycreeps)
        {
            const tmpdamage = getMaxDamgePossible(e,mycreeps);
            if(sum_maxDamage<tmpdamage)
            {
                sum_maxDamage = tmpdamage ;
            }
        }

        return sum_maxDamage;
    }

    protected static possibleMaxDamage( hostiles:Creep[],hostileCreepAbility: Record<string, Record<number, number>> ):number
    {
        let possdamage_max = 0;
        for(const e of hostiles)
        {
            if(!hostileCreepAbility[e.id])
            {
                continue;
            }
            possdamage_max+=hostileCreepAbility[e.id][1];
        }
        return possdamage_max
    }
    protected static possibleDamage(mycreeps:Creep[],hostiles:Creep,atk:number,range:number,extend_range:number ):Record<number,number>
    {
        const possible_atk:Record<number,number>={};
        for(const e of mycreeps)
        {

            const distance =e.nextpos.distance(hostiles.pos);
            if(distance<=(range+extend_range))
            {
                possible_atk[e.nextpos.to1D()]= atk;
            }

        }
        return possible_atk
    }

     /**
     *
     * @returns 获取周围敌方单位 对小队的攻击 影响 值，有攻击力 距离 方向决定
     */
     
      public static getHostileField(team:ATeamCombat):IFVector2
      {
          const anchor = team.getAnchor();
          const cachecreeps =  global.world.PollHostiles(anchor.roomName);
  
          let field:IFVector2 = {x:0,y:0};
          let count=0;
          if(cachecreeps && cachecreeps.hostileCreepAbility)
          {
              for(const hostcreep of team.aroundHostileCreeps)
              {
                  if(!cachecreeps.hostileCreepAbility[hostcreep.id])
                  {
                      global.Log.Error(`找不到对应的攻击力数值:${hostcreep.name}_${JSON.stringify(hostcreep.pos)}`)
                      continue;
                  }
                  let Abi = cachecreeps.hostileCreepAbility[hostcreep.id][1];
                  if(!Abi)
                  {
                      Abi=cachecreeps.hostileCreepAbility[hostcreep.id][3];
                  }
  
                  if(Abi)
                  {
                      const dis = Math2D.distanceto(anchor,hostcreep.pos);
                      const offset = Math2D.subtract(anchor,hostcreep.pos);
                      const tmpfield = Math2D.multiply(offset,Abi/(dis*dis));
                      field=Math2D.add(field,tmpfield);
                      count++;
                  }
              }
          }
          if(count==0)
          {
                team.log("info",`${team.GUID()}->周围攻击性单位为0`);
              return field;
          }
          return Math2D.multiply(field,1/count);
      }
}
